export default function bwPowerSet(originalSet) {
  // 创建最后输出的数组
  const subSets = [];

  // We will have 2^n possible combinations (where n is a length of original set).
  // It is because for every element of original set we will decide whether to include
  // it or not (2 options for each set element).

  // 数组里面的每个数据都有两种状态：选中或不选中，所以有2^n种组合
  const numberOfCombinations = 2 ** originalSet.length;

  // Each number in binary representation in a range from 0 to 2^n does exactly what we need:
  // it shows by its bits (0 or 1) whether to include related element from the set or not.
  // For example, for the set {1, 2, 3} the binary number of 0b010 would mean that we need to
  // include only "2" to the current set.

  // 遍历所有可能的组合
  for (
    let combinationIndex = 0;
    combinationIndex < numberOfCombinations;
    combinationIndex += 1
  ) {
    // 遍历每一层的时候都会创建一个数组
    const subSet = [];

    // 这里进行第二次遍历，用来确定要不要往数组里面添加元素
    for (
      let setElementIndex = 0;
      // 遍历玩所有数组即可
      setElementIndex < originalSet.length;
      setElementIndex += 1
    ) {
      // Decide whether we need to include current element into the subset or not.

      // << 位运算符号，代表左移后面的位数（会以二进制的方式进行存储）
      // 此时进行按位与运算二进制，及对二进制的每一位进行与运算
      // 如：8(1000) & 4(0100) = 0 ，8(1000) & (0010) = 2
      if (combinationIndex & (1 << setElementIndex)) {
        // 如果条件成立，就会把该数组中的索引为 setElementIndex 的元素添加到内侧 subSet 中
        subSet.push(originalSet[setElementIndex]);
      }
    }

    // Add current subset to the list of all subsets.

    // 把内侧循环的数组添加到最终数组里面
    subSets.push(subSet);
  }

  return subSets;
}
